home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 12 / Cream of the Crop 12 (Part II) / Cream of the Crop 12 (Part II).iso / OS2 / KONSTR21.ZIP / konstr / SOURCE / easy.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1996-03-20  |  43.7 KB  |  1,880 lines

  1. #include "easy.h"
  2.  
  3. #include <math.h>
  4.  
  5. static int window_invalid=0;
  6. static StandardWindow *actwindow;
  7.  
  8. // ******************* Debug tools **********************
  9.  
  10. void dumplong (long n)
  11. {    char s[256];
  12.     sprintf(s,"%ld, %lx %c",n,n,(char)n);
  13.     WinMessageBox(HWND_DESKTOP,HWND_DESKTOP,s,"Dump",0,
  14.         MB_OK);
  15. }
  16.  
  17. void dump (char *s)
  18. {    WinMessageBox(HWND_DESKTOP,HWND_DESKTOP,s,"Dump",0,
  19.         MB_OK);
  20. }
  21.  
  22. // *********** Messages etc. ***************************
  23.  
  24. void Message (char *s, char *title)
  25. {    WinMessageBox(HWND_DESKTOP,HWND_DESKTOP,s,title,0,
  26.         MB_OK|MB_INFORMATION);
  27. }
  28.  
  29. void Warning (char *s, char *title)
  30. {    WinMessageBox(HWND_DESKTOP,HWND_DESKTOP,s,title,0,
  31.         MB_OK|MB_WARNING);
  32. }
  33.  
  34. int Question (char *s, char *title)
  35. {    return WinMessageBox(HWND_DESKTOP,HWND_DESKTOP,s,title,0,
  36.         MB_YESNO|MB_QUERY);
  37. }
  38.  
  39. int QuestionAbort (char *s, char *title)
  40. {    return WinMessageBox(HWND_DESKTOP,HWND_DESKTOP,s,title,0,
  41.         MB_YESNOCANCEL|MB_QUERY);
  42. }
  43.  
  44. void Message (char *s, char *title, Window &w)
  45. {    WinMessageBox(HWND_DESKTOP,w.handle(),s,title,0,
  46.         MB_OK|MB_INFORMATION);
  47. }
  48.  
  49. void Warning (char *s, char *title, Window &w)
  50. {    WinMessageBox(HWND_DESKTOP,w.handle(),s,title,0,
  51.         MB_OK|MB_WARNING);
  52. }
  53.  
  54. int Question (char *s, char *title, Window &w)
  55. {    return WinMessageBox(HWND_DESKTOP,w.handle(),s,title,0,
  56.         MB_YESNO|MB_QUERY);
  57. }
  58.  
  59. int QuestionAbort (char *s, char *title, Window &w)
  60. {    return WinMessageBox(HWND_DESKTOP,w.handle(),s,title,0,
  61.         MB_YESNOCANCEL|MB_QUERY);
  62. }
  63.  
  64. void Beep (int f, double sec)
  65. {    DosBeep(f,sec*1000);
  66. }
  67.  
  68. // **************** Threads **********************
  69.  
  70. void _syscall ThreadProc (Thread *s)
  71. {    s->call();
  72.     s->finished();
  73.     _endthread();
  74. }
  75.  
  76. void Thread::start (Parameter p)
  77. {   stop();
  78.     P=p;
  79.     Started=1; Expected=0;
  80.     Tid=_beginthread(
  81.         (void (_USERENTRY *) (void *))ThreadProc,
  82.         Stacksize,Parameter(this));
  83.     if (Tid==(TID)-1) Started=0;
  84. }
  85.  
  86. void Thread::stop ()
  87. {    if (Started) DosKillThread(Tid);
  88.     Started=0; Expected=0;
  89. }
  90.  
  91. void Thread::suspend ()
  92. {    if (Started) DosSuspendThread(Tid);
  93. }
  94.  
  95. void Thread::resume ()
  96. {    if (Started) DosResumeThread(Tid);
  97. }
  98.  
  99. void Thread::wait ()
  100. {   TID tid=Tid;
  101.     Expected=1;
  102.     if (Started) DosWaitThread(&tid,DCWW_WAIT);
  103. }
  104.  
  105. // **************** Time *************************
  106.  
  107. void Time::set ()
  108. {   long sec;
  109.     DosQuerySysInfo(QSV_TIME_LOW,QSV_TIME_LOW,
  110.         &sec,sizeof(unsigned long));
  111.     Seconds=sec;
  112. }
  113.  
  114. // ********************* Strings ************************
  115.  
  116. long String::defaultsize=32;
  117.  
  118. String::String (char *text, long size)
  119. {   if (!text) text="";
  120.     Size=strlen(text);
  121.     if (Size<size) Size=size;
  122.     P=new char[Size+1];
  123.     strcpy(P,text);
  124. }
  125.  
  126. String::String (String &s)
  127. {    Size=s.Size;
  128.     P=new char[Size+1];
  129.     strcpy(P,s.P);
  130. }
  131.  
  132. String::String (int id)
  133. {   char s[1024];
  134.     WinLoadString(program.hab(),NULLHANDLE,id,1022,s);
  135.     Size=strlen(s);
  136.     P=new char[Size+1];
  137.     strcpy(P,s);
  138. }
  139.  
  140.  
  141. String::String ()
  142. {   Size=defaultsize;
  143.     P=new char[Size+1];
  144.     *P=0;
  145. }
  146.  
  147. String::~String ()
  148. {    delete P;
  149. }
  150.  
  151. void String::copy (char *text, long size)
  152. {    long textsize=strlen(text);
  153.     if (textsize>size) size=textsize;
  154.     if (Size<size)
  155.     {   char *p=P;
  156.         Size=size;
  157.         P=new char[Size+1];
  158.         strcpy(P,text);
  159.         delete p;
  160.     }
  161.     else strcpy(P,text);
  162. }
  163.  
  164. void String::copy (char *text)
  165. {    long size=strlen(text);
  166.     if (Size<size)
  167.     {   char *p=P;
  168.         Size=size;
  169.         P=new char[Size+1];
  170.         strcpy(P,text);
  171.         delete p;
  172.     }
  173.     else strcpy(P,text);
  174. }
  175.  
  176. void String::cat (char *text)
  177. {   long total;
  178.     if ((total=strlen(P)+strlen(text))>Size)
  179.     {    copy(P,total);
  180.     }
  181.     strcat(P,text);
  182. }
  183.  
  184. char *String::filename ()
  185. {    char *p=P+strlen(P);
  186.     while (p>P)
  187.     {    if (*p=='\\' || *p==':') return p+1;
  188.         p--;
  189.     }
  190.     return p;
  191. }
  192.  
  193. char *String::extension ()
  194. {    char *p=P+strlen(P);
  195.     while (p>P)
  196.     {    if (*p=='\\' || *p=='.') break;
  197.         p--;
  198.     }
  199.     if (p>=P && *p=='.') return p;
  200.     return P+strlen(P);
  201. }
  202.  
  203. void String::extension (char *ext)
  204. {   *extension()=0;
  205.     cat(ext);
  206. }
  207.  
  208. int String::testextension (char *ext)
  209. {    char *p=extension();
  210.     while (*p && *ext)
  211.     {   if (::toupper(*p)!=::toupper(*ext)) return 0;
  212.         p++; ext++;
  213.     }
  214.     if (!*p && !*ext) return 1;
  215.     return 0;
  216. }
  217.  
  218. void String::stripfilename ()
  219. {    *filename()=0;
  220. }
  221.  
  222. void String::setname (char *name)
  223. {    stripfilename();
  224.     cat(name);
  225. }
  226.  
  227. int String::todouble (double &x)
  228. {    int n;
  229.     if (sscanf(P,"%lg%n",&x,&n)==0) return 0;
  230.     char *p=P+n;
  231.     if (*p) return 0;
  232.     else return 1;
  233. }
  234.  
  235. int String::tolong (long &x)
  236. {    int n;
  237.     if (sscanf(P,"%ld%n",&x,&n)==0) return 0;
  238.     char *p=P+n;
  239.     if (*p) return 0;
  240.     else return 1;
  241. }
  242.  
  243. void String::toupper ()
  244. {    char *p=P;
  245.     while (*p)
  246.     {    *p=::toupper(*p);
  247.         p++;
  248.     }
  249. }
  250.  
  251. // ****************** Rectangle *************************
  252.  
  253. void Rectangle::minsize (LONG wmin, LONG hmin)
  254. {    if (W<0 && -W<wmin) W=-wmin;
  255.     else if (W>=0 && W<wmin) W=wmin;
  256.     if (H<0 && -H<hmin) H=-hmin;
  257.     else if (H>=0 && H<hmin) H=hmin;
  258. }
  259.  
  260. void Rectangle::hrescale (double scale)
  261. {    H=(LONG)(scale*abs(W))*(H<0?-1:1);
  262. }
  263.  
  264. void Rectangle::wrescale (double scale)
  265. {    W=(LONG)(scale*abs(H))*(W<0?-1:1);
  266. }
  267.  
  268. // ******************** Program *************************
  269.  
  270. MRESULT EXPENTRY MainWindowProc (HWND hwnd, unsigned long msg,
  271.     MPARAM mp1, MPARAM mp2)
  272. {    StandardWindow *window;
  273.     clicktype click;
  274.     if (window_invalid) window=actwindow;
  275.     else window=(StandardWindow *)WinQueryWindowPtr(hwnd,QWL_USER);
  276.     POINTS *points;
  277.     switch (msg)
  278.     {   case WM_CREATE :
  279.             window->Handle=hwnd;
  280.             break;
  281.         case WM_PRESPARAMCHANGED :
  282.             window->pres_changed();
  283.             goto def;
  284.         case WM_PAINT :
  285.             {    RedrawPS ps(hwnd,*window);
  286.                 window->redraw(ps);
  287.             }
  288.             break;
  289.         case WM_SIZE :
  290.             if (SHORT1FROMMP(mp2)==0) goto def;
  291.             if (window->Width==SHORT1FROMMP(mp2) &&
  292.                 window->Height==SHORT2FROMMP(mp2)) goto def;
  293.             window->Width=SHORT1FROMMP(mp2);
  294.             window->Height=SHORT2FROMMP(mp2);
  295.             window->sized();
  296.             break;
  297.         case WM_CHAR :
  298.             if (window->key(SHORT1FROMMP(mp1),SHORT1FROMMP(mp2),
  299.                 SHORT2FROMMP(mp2))) break;
  300.             goto def;
  301.         case WM_HSCROLL :
  302.             if (window->hscrolled(SHORT2FROMMP(mp2),SHORT1FROMMP(mp2)))
  303.                 break;
  304.             goto def;
  305.         case WM_VSCROLL :
  306.             if (window->vscrolled(SHORT2FROMMP(mp2),SHORT1FROMMP(mp2)))
  307.                 break;
  308.             goto def;
  309.         case WM_BUTTON1CLICK :
  310.             click=button1; goto button;
  311.         case WM_BUTTON2CLICK :
  312.             click=button2; goto button;
  313.         case WM_BUTTON3CLICK :
  314.             click=button3; goto button;
  315.         case WM_BUTTON1UP :
  316.             click=button1up; goto button;
  317.         case WM_BUTTON2UP :
  318.             click=button2up; goto button;
  319.         case WM_BUTTON3UP :
  320.             click=button3up; goto button;
  321.         case WM_BUTTON1DOWN :
  322.             click=button1down; goto button;
  323.         case WM_BUTTON2DOWN :
  324.             click=button2down; goto button;
  325.         case WM_BUTTON3DOWN :
  326.             click=button3down; goto button;
  327.         case WM_BUTTON1DBLCLK :
  328.             click=button1double; goto button;
  329.         case WM_BUTTON2DBLCLK :
  330.             click=button2double; goto button;
  331.         case WM_MOUSEMOVE :
  332.             WinSetPointer(HWND_DESKTOP,window->New);
  333.             click=mousemove; goto button;
  334.         case WM_BUTTON3DBLCLK :
  335.             click=button3double;
  336.             button: points=(POINTS *)&mp1;
  337.             window->clicked(points->x,points->y,click,
  338.                 SHORT2FROMMP(mp2));
  339.             break;
  340.         case WM_COMMAND :
  341.             if (window->Dlg)
  342.                 if (window->Dlg->command(
  343.                     (Parameter)mp1,(Parameter)mp2)) break;
  344.             if (window->Windowmenu)
  345.                 if (window->Windowmenu->call(SHORT1FROMMP(mp1)))
  346.                     break;
  347.             goto def;
  348.         case WM_SHOW :
  349.             window->Visible=SHORT1FROMMP(mp1);
  350.             goto def;
  351.         case WM_CLOSE :
  352.             if (window->close()) goto def;
  353.             break;
  354.         case WM_TIMER :
  355.             window->timer(SHORT1FROMMP(mp1));
  356.             break;
  357.         case WM_SEM1 :
  358.             window->semaphore(1,(long)mp1); break;
  359.         case WM_SEM2 :
  360.             window->semaphore(2,(long)mp1); break;
  361.         case WM_SEM3 :
  362.             window->semaphore(3,(long)mp1); break;
  363.         case WM_SEM4 :
  364.             window->semaphore(4,(long)mp1); break;
  365.         default :
  366.             def: return WinDefWindowProc(hwnd,msg,mp1,mp2);
  367.     }
  368.     return (MRESULT)FALSE;
  369. }
  370.  
  371. Program::Program (int style, int size)
  372. {    Hab=WinInitialize(0);
  373.     Hmq=WinCreateMsgQueue(Hab,size);
  374.     WinRegisterClass(Hab,"EasyMainWindow",MainWindowProc,
  375.         style,sizeof(StandardWindow *));
  376.     HPS hps=WinGetScreenPS(HWND_DESKTOP);
  377.     GpiQueryFontMetrics(hps,sizeof(FONTMETRICS),
  378.         &F);
  379.     WinReleasePS(hps);
  380. }
  381.  
  382. Program::~Program ()
  383. {    WinDestroyMsgQueue(Hmq);
  384.     WinTerminate(Hab);
  385. }
  386.  
  387. inline int Program::getmessage ()
  388. {    return WinGetMsg(Hab,&Qmsg,0L,0,0);
  389. }
  390.  
  391. inline void Program::dispatch ()
  392. {    WinDispatchMsg(Hab,&Qmsg);
  393. }
  394.  
  395. void Program::loop ()
  396. {    while(getmessage())
  397.         dispatch();
  398. }
  399.  
  400. void Program::clear_messages ()
  401. {    while (WinPeekMsg(Hab,&Qmsg,0L,0,0,PM_REMOVE))
  402.         dispatch();
  403. }
  404.  
  405. // ************** Window ******************************
  406.  
  407. Window::Window ()
  408. {    New=Old=WinQuerySysPointer(HWND_DESKTOP,pointer_arrow,TRUE);
  409. }
  410.  
  411. void Window::size (long w, long h)
  412. {   WinSetWindowPos(Handle,NULLHANDLE,0,0,
  413.         w,h,SWP_SIZE);}
  414.  
  415. void Window::pos (long x, long y)
  416. {    WinSetWindowPos(Handle,NULLHANDLE,x,y,
  417.         0,0,SWP_MOVE);
  418. }
  419.  
  420. void Window::pos (long &x, long &y, long &w, long &h)
  421. {   SWP p;
  422.     WinQueryWindowPos(Handle,&p);
  423.     x=p.x; y=p.y; w=p.cx; h=p.cy;
  424. }
  425.  
  426. void Window::setpointer (pointertype p)
  427. {    New=WinQuerySysPointer(HWND_DESKTOP,p,FALSE);
  428.     WinSetPointer(HWND_DESKTOP,New);
  429. }
  430.  
  431. void Window::setpointer (Pointer &p)
  432. {    New=p.handle();
  433.     WinSetPointer(HWND_DESKTOP,New);
  434. }
  435.  
  436. void Window::resetpointer ()
  437. {    WinSetPointer(HWND_DESKTOP,Old);
  438.     New=Old;
  439. }
  440.  
  441. void Window::showpointer ()
  442. {    WinShowPointer(HWND_DESKTOP,TRUE);
  443. }
  444.  
  445. void Window::hidepointer ()
  446. {    WinShowPointer(HWND_DESKTOP,FALSE);
  447. }
  448.  
  449. // ************* Standard Window ***********************
  450.  
  451. int StandardWindow::msg_semaphore[4]=
  452.     { WM_SEM1,WM_SEM2,WM_SEM3,WM_SEM4 };
  453.  
  454. void StandardWindow::size (LONG w, LONG h)
  455. {   RECTL r;
  456.     r.xLeft=r.yBottom=0; r.xRight=w; r.yTop=h;
  457.     WinCalcFrameRect(FrameHandle,&r,FALSE);
  458.     SWP s;
  459.     WinQueryWindowPos(FrameHandle,&s);
  460.     h=r.yTop-r.yBottom;
  461.     WinSetWindowPos(FrameHandle,NULLHANDLE,
  462.         s.x,(s.y+s.cy)-h,
  463.         r.xRight-r.xLeft,h,
  464.         SWP_SIZE|SWP_MOVE);
  465. }
  466.  
  467. void StandardWindow::framepos (long x, long y)
  468. {    WinSetWindowPos(FrameHandle,NULLHANDLE,x,y,
  469.         0,0,SWP_MOVE);
  470. }
  471.  
  472. void StandardWindow::getframe (long &x, long &y,
  473.     long &w, long &h)
  474. {    SWP s;
  475.     WinQueryWindowPos(FrameHandle,&s);
  476.     x=s.x; y=s.y; w=s.cx; h=s.cy;
  477. }
  478.  
  479. void StandardWindow::center ()
  480. {    long x,y,w,h;
  481.     getframe(x,y,w,h);
  482.     framepos(program.width()/2-w/2,program.height()/2-h/2);
  483. }
  484.  
  485. void StandardWindow::init (int style)
  486. {   window_invalid=1;
  487.     actwindow=this;
  488.     FrameHandle=WinCreateStdWindow(HWND_DESKTOP,
  489.         style,&Flags,"EasyMainWindow",
  490.         (char *)Name,0,
  491.         (HMODULE)0,Id,&Handle);
  492.     WinSetWindowPtr(Handle,QWL_USER,this);
  493.     window_invalid=0;
  494.     Windowmenu=NULL;
  495.     Visible=1;
  496. }
  497.  
  498. StandardWindow::~StandardWindow ()
  499. {    WinDestroyWindow(FrameHandle);
  500. }
  501.  
  502. StandardWindow::StandardWindow (int id, char *name,
  503.     unsigned long flags)
  504.     : Name(name),Dlg(0)
  505. {    Id=id; Flags=flags;
  506. }
  507.  
  508. void StandardWindow::top ()
  509. {    WinSetWindowPos(FrameHandle,
  510.         HWND_TOP,0,0,0,0,SWP_ZORDER);
  511.     WinSetFocus(HWND_DESKTOP,Handle);
  512. }
  513.  
  514. int StandardWindow::topped ()
  515. {    return WinQueryWindow(HWND_DESKTOP,QW_TOP)==FrameHandle;
  516. }
  517.  
  518. int StandardWindow::rubberbox (LONG x, LONG y, clicktype click,
  519.     Rectangle &R, LONG wmin, LONG hmin, double wscale, double hscale)
  520. {   WindowPS ps(*this);
  521.     ps.mix(FM_XOR);
  522.     switch (click)
  523.     {    case button1down :
  524.             capture();
  525.             Rubber=1;
  526.             R=Rectangle(x,y,wmin,hmin);
  527.             ps.frame(R,0,CLR_GREEN);
  528.             return RUBBER_START;
  529.         case mousemove :
  530.             if (!Rubber) break;
  531.             ps.frame(R,0,CLR_GREEN);
  532.             R.resize(x-R.x(),y-R.y());
  533.             R.minsize(hmin,wmin);
  534.             if (wscale>0) R.wrescale(wscale);
  535.             if (hscale>0) R.hrescale(hscale);
  536.             ps.frame(R,0,CLR_GREEN);
  537.             Rubber=2;
  538.             break;
  539.         case button1up :
  540.             capture(0);
  541.             ps.frame(R,0,CLR_GREEN);
  542.             if (!Rubber || Rubber==1)
  543.             {    Rubber=0;
  544.                 return RUBBER_CANCEL;
  545.             }
  546.             Rubber=0;
  547.             if (abs(y-R.y())>=hmin) return RUBBER_DONE;
  548.             else return RUBBER_CANCEL;
  549.     }
  550.     return RUBBER_ZERO;
  551. }
  552.  
  553. void StandardWindow::vscroll (int pos, int min, int max)
  554. {    HWND h=WinWindowFromID(FrameHandle,FID_VERTSCROLL);
  555.     WinSendMsg(h,SBM_SETSCROLLBAR,MPFROMSHORT(pos),
  556.         MPFROM2SHORT(min,max));
  557. }
  558.  
  559. void StandardWindow::hscroll (int pos, int min, int max)
  560. {    HWND h=WinWindowFromID(FrameHandle,FID_HORZSCROLL);
  561.     WinSendMsg(h,SBM_SETSCROLLBAR,MPFROMSHORT(pos),
  562.         MPFROM2SHORT(min,max));
  563. }
  564.  
  565. void StandardWindow::title (char *s)
  566. {    HWND h=WinWindowFromID(FrameHandle,FID_TITLEBAR);
  567.     Name.copy(s);
  568.     WinSetWindowText(h,Name);
  569. }
  570.  
  571. // ************* Menus ************************************
  572.  
  573. Menu::~Menu ()
  574. {   Menuentry *Mp1;
  575.     while (Mp)
  576.     {   Mp1=Mp;
  577.         Mp=Mp->next();
  578.         delete Mp1;
  579.     }
  580. }
  581.  
  582. int Menu::call (int command)
  583. {    Menuentry *m=Mp;
  584.     Command=command;
  585.     while (m)
  586.         if (m->command()==command)
  587.         {    m->call(command);
  588.             return 1;
  589.         }
  590.         else m=m->next();
  591.     return 0;
  592. }
  593.  
  594. void Menu::enable (int id, int flag)
  595. {    HWND handle=WinWindowFromID(W->framehandle(),FID_MENU);
  596.     WinSendMsg(handle,MM_SETITEMATTR,
  597.         MPFROM2SHORT(id,TRUE),MPFROM2SHORT(MIA_DISABLED,
  598.         flag?0:MIA_DISABLED));
  599. }
  600.  
  601. void Menu::check (int id, int flag)
  602. {    HWND handle=WinWindowFromID(W->framehandle(),FID_MENU);
  603.     WinSendMsg(handle,MM_SETITEMATTR,
  604.         MPFROM2SHORT(id,TRUE),MPFROM2SHORT(MIA_CHECKED,
  605.         flag?MIA_CHECKED:0));
  606. }
  607.  
  608. HWND Menu::submenu (int id)
  609. {   MENUITEM mi;
  610.     HWND handle=WinWindowFromID(W->framehandle(),FID_MENU);
  611.     WinSendMsg(handle,MM_QUERYITEM,
  612.         MPFROM2SHORT(id,TRUE),(MPARAM)&mi);
  613.     return mi.hwndSubMenu;
  614. }
  615.  
  616. void Menu::additem (int id,
  617.     Menuproc *proc, char *entry, int menuid, int pos)
  618. {    HWND handle=submenu(menuid);
  619.     MENUITEM mi;
  620.     mi.iPosition=pos;
  621.     mi.afStyle=MIS_TEXT;
  622.     mi.afAttribute=0;
  623.     mi.id=id;
  624.     mi.hwndSubMenu=NULLHANDLE;
  625.     mi.hItem=0;
  626.     WinSendMsg(handle,MM_INSERTITEM,(MPARAM)&mi,
  627.         (MPARAM)entry);
  628.     add(id,proc);
  629. }
  630.  
  631. void Menu::removeitem (int id, int menuid)
  632. {    HWND handle=submenu(menuid);
  633.     WinSendMsg(handle,MM_DELETEITEM,
  634.         MPFROM2SHORT(id,TRUE),NULL);
  635.     remove(id);
  636. }
  637.  
  638. void Menu::remove (int id)
  639. {    Menuentry *mp=Mp;
  640.     if (!mp) return;
  641.     if (mp && mp->command()==id)
  642.     {    mp=mp->next();
  643.         delete mp;
  644.         return;
  645.     }
  646.     while (mp)
  647.     {    if (mp->next()->command()==id)
  648.         {    mp->next(mp->next()->next());
  649.             delete mp->next();
  650.             break;
  651.         }
  652.     }
  653. }
  654.  
  655. //******************** Palettes ***************************
  656.  
  657. Palette::Palette (unsigned long a[], int n, int opt)
  658. {   long option=0;
  659.     if (opt&pure) option|=LCOL_PURECOLOR;
  660.     if (opt&own) option|=LCOL_OVERRIDE_DEFAULT_COLORS;
  661.     Handle=GpiCreatePalette(program.hab(),option,LCOLF_CONSECRGB,n,a);
  662. }
  663.  
  664. Palette::~Palette ()
  665. {    GpiDeletePalette(Handle);
  666. }
  667.  
  668. // ************* Presentation Space class (PS) *************
  669.  
  670. void PS::clip (long x, long y, long w, long h)
  671. {    RECTL r;
  672.     r.xLeft=x+X; r.xRight=x+X+w-1; r.yBottom=y+Y; r.yTop=y+Y+h-1;
  673.     GpiIntersectClipRectangle(Handle,&r);
  674.     S.cx=w; S.cy=h;
  675. }
  676.  
  677. void PS::directcolor (int pure)
  678. {    GpiCreateLogColorTable(Handle,pure?LCOL_PURECOLOR:0,
  679.                 LCOLF_RGB,0,0,NULL);
  680. }
  681.  
  682. void PS::defaultcolors ()
  683. {    GpiCreateLogColorTable(Handle,LCOL_RESET,0,0,0,NULL);
  684. }
  685.  
  686. void PS::move (LONG c, LONG r, Color col)
  687. {   color(col);
  688.     P.x=c+X; P.y=r+Y; GpiMove(Handle,&P);
  689. }
  690.  
  691. void PS::linerel (LONG w, LONG h, Color col)
  692. {   color(col);
  693.     P.x+=w; P.y+=h; GpiLine(Handle,&P);
  694. }
  695.  
  696. void PS::lineto (LONG c, LONG r, Color col)
  697. {   color(col);
  698.     P.x=c+X; P.y=r+Y; GpiLine(Handle,&P);
  699. }
  700.  
  701. void PS::point (LONG c, LONG r, Color col)
  702. {   color(col);
  703.     P.x=c+X; P.y=r+Y; GpiSetPel(Handle,&P);
  704. }
  705.  
  706. void PS::text (char *s, Color col, unsigned long al, unsigned long val)
  707. {    color(col);
  708.     GpiSetTextAlignment(Handle,al,val);
  709.     GpiCharString(Handle,strlen(s),s);
  710. }
  711.  
  712. void PS::clippedtext (char *s, long x, long y,
  713.     long x1, long y1, long x2, long y2,
  714.     Color col, unsigned long al, unsigned long val)
  715. {   RECTL r={x1,y1,x2,y2};
  716.     POINTL p={x,y};
  717.     color(col);
  718.     GpiSetTextAlignment(Handle,al,val);
  719.     GpiCharStringPosAt(Handle,&p,&r,CHS_CLIP,strlen(s),s,NULL);
  720. }
  721.  
  722. void PS::textbox (char *text, long &width, long &height)
  723. {   POINTL pts[4];
  724.     GpiQueryTextBox(Handle,strlen(text),text,4,pts);
  725.     width=pts[2].x-pts[0].x;
  726.     height=pts[0].y-pts[3].y;
  727. }
  728.  
  729. double PS::textextend (char *text, double vx, double vy)
  730. {   POINTL pts[4];
  731.     int i;
  732.     double emin,emax,r,h;
  733.     GpiQueryTextBox(Handle,strlen(text),text,4,pts);
  734.     r=sqrt(vx*vx+vy*vy); vx/=r; vy/=r;
  735.     pts[0].x--; pts[1].x--;
  736.     pts[2].x++; pts[2].x++;
  737.     emin=emax=vx*pts[0].x+vy*pts[0].y;
  738.     for (i=1; i<4; i++)
  739.     {    h=vx*pts[i].x+vy*pts[i].y;
  740.         if (h<emin) emin=h;
  741.         else if (h>emax) emax=h;
  742.     }
  743.     return emax-emin;
  744. }
  745.  
  746. void PS::frame (LONG w, LONG h, int r, Color col)
  747. {    color(col);
  748.     P.x+=w-1; P.y+=h-1; GpiBox(Handle,DRO_OUTLINE,&P,r,r);
  749. }
  750.  
  751. void PS::area (LONG w, LONG h, int r, Color col)
  752. {    color(col);
  753.     GpiSetBackMix(Handle,BM_OVERPAINT);
  754.     GpiSetPattern(Handle,PATSYM_SOLID);
  755.     P.x+=w-1; P.y+=h-1; GpiBox(Handle,DRO_FILL,&P,r,r);
  756.     GpiSetBackMix(Handle,BM_LEAVEALONE);
  757. }
  758.  
  759. void PS::backarea (LONG w, LONG h)
  760. {    GpiSetBackMix(Handle,BM_OVERPAINT);
  761.     GpiSetPattern(Handle,PATSYM_BLANK);
  762.     P.x+=w-1; P.y+=h-1; GpiBox(Handle,DRO_FILL,&P,0,0);
  763.     GpiSetBackMix(Handle,BM_LEAVEALONE);
  764. }
  765.  
  766. void PS::framedarea (LONG w, LONG h, int r, Color col)
  767. {    color(col);
  768.     GpiSetBackMix(Handle,BM_OVERPAINT);
  769.     GpiSetPattern(Handle,PATSYM_BLANK);
  770.     P.x+=w-1; P.y+=h-1; GpiBox(Handle,DRO_OUTLINEFILL,&P,r,r);
  771.     GpiSetBackMix(Handle,BM_LEAVEALONE);
  772. }
  773.  
  774. void PS::frame (Rectangle &R, int r, Color col)
  775. {    move(R.x1(),R.y1());
  776.     frame(abs(R.w()),abs(R.h()),r,col);
  777. }
  778.  
  779. void PS::area (Rectangle &R, int r, Color col)
  780. {    move(R.x1(),R.y1());
  781.     area(abs(R.w()),abs(R.h()),r,col);
  782. }
  783.  
  784. void PS::framedarea (Rectangle &R, int r, Color col)
  785. {    move(R.x1(),R.y1());
  786.     framedarea(abs(R.w()),abs(R.h()),r,col);
  787. }
  788.  
  789. void PS::mark (LONG c, LONG r, unsigned long type, Color col)
  790. {   color(col);
  791.     GpiSetMarker(Handle,type);
  792.     P.x=c+X; P.y=r+Y; GpiMarker(Handle,&P);
  793. }
  794.  
  795. void PS::circle (LONG c, LONG r, LONG rad, double factor,
  796.     Color col)
  797. {   ARCPARAMS p;
  798.     p.lP=rad; p.lS=0;
  799.     p.lQ=rad*factor; p.lR=0;
  800.     GpiSetArcParams(Handle,&p);
  801.     move(c,r);
  802.     color(col);
  803.     GpiFullArc(Handle,DRO_OUTLINE,65536l);
  804. }
  805.  
  806. void PS::filledcircle (LONG c, LONG r, LONG rad, double factor,
  807.     Color col, Color fillcol)
  808. {   ARCPARAMS p;
  809.     p.lP=rad; p.lS=0;
  810.     p.lQ=rad*factor; p.lR=0;
  811.     GpiSetArcParams(Handle,&p);
  812.     move(c,r);
  813.     color(fillcol);
  814.     if ((long)col==CLR_DEFAULT) GpiFullArc(Handle,DRO_OUTLINEFILL,65536l);
  815.     else GpiFullArc(Handle,DRO_FILL,65536l);
  816.     if ((long)col!=CLR_DEFAULT)
  817.     {    move(c,r);
  818.         color(col);
  819.         GpiFullArc(Handle,DRO_OUTLINE,65536l);
  820.     }
  821. }
  822.  
  823. void PS::arc (LONG c, LONG r, LONG rad, double factor,
  824.     double phi1, double phi2, Color col)
  825. {   ARCPARAMS p;
  826.     p.lP=rad; p.lS=0;
  827.     p.lQ=rad*factor; p.lR=0;
  828.     GpiSetArcParams(Handle,&p);
  829.     move(c,r);
  830.     color(col);
  831.     double delta;
  832.     if (phi1<0) phi1+=360;
  833.     if (phi2<0) phi2+=360;
  834.     if (phi2>=phi1) delta=phi2-phi1;
  835.     else delta=phi2+360-phi1;
  836.     GpiSetLineType(Handle,LINETYPE_INVISIBLE);
  837.     GpiPartialArc(Handle,&P,65536l,phi1*65536l,0);
  838.     GpiSetLineType(Handle,LINETYPE_SOLID);
  839.     GpiPartialArc(Handle,&P,65536l,
  840.         phi1*65536l,delta*65536l);
  841. }
  842.  
  843. void PS::filledpie (LONG c, LONG r, LONG rad, double factor,
  844.     double phi1, double phi2, Color col, Color fillcol)
  845. {   ARCPARAMS p;
  846.     double delta;
  847.     p.lP=rad; p.lS=0;
  848.     p.lQ=rad*factor; p.lR=0;
  849.     GpiSetArcParams(Handle,&p);
  850.     if (phi1<0) phi1+=360;
  851.     if (phi2<0) phi2+=360;
  852.     if (phi2>=phi1) delta=phi2-phi1;
  853.     else delta=phi2+360-phi1;
  854.     color(fillcol);
  855.     if ((long)col==CLR_DEFAULT) GpiBeginArea(Handle,BA_BOUNDARY);
  856.     else GpiBeginArea(Handle,BA_NOBOUNDARY);
  857.     move(c,r);
  858.     GpiSetLineType(Handle,LINETYPE_SOLID);
  859.     GpiPartialArc(Handle,&P,65536l,phi1*65536l,delta*65536l);
  860.     GpiLine(Handle,&P);
  861.     GpiEndArea(Handle);
  862.     if ((long)col!=CLR_DEFAULT)
  863.     {   color(col);
  864.         GpiPartialArc(Handle,&P,65536l,
  865.             phi1*65536l,delta*65536l);
  866.         GpiLine(Handle,&P);
  867.     }
  868. }
  869.  
  870. void PS::pie (LONG c, LONG r, LONG rad, double factor,
  871.     double phi1, double phi2, Color col)
  872. {   ARCPARAMS p;
  873.     double delta;
  874.     p.lP=rad; p.lS=0;
  875.     p.lQ=rad*factor; p.lR=0;
  876.     GpiSetArcParams(Handle,&p);
  877.     if (phi1<0) phi1+=360;
  878.     if (phi2<0) phi2+=360;
  879.     if (phi2>=phi1) delta=phi2-phi1;
  880.     else delta=phi2+360-phi1;
  881.     move(c,r);
  882.     color(col);
  883.     GpiSetLineType(Handle,LINETYPE_SOLID);
  884.     GpiPartialArc(Handle,&P,65536l,phi1*65536l,delta*65536l);
  885.     GpiLine(Handle,&P);
  886. }
  887.  
  888. void PS::setfont (Font &font, int id)
  889. {   GpiCreateLogFont(Handle,NULL,id,font.fat());
  890.     GpiSetCharSet(Handle,id);
  891. }
  892.  
  893. void PS::image (long w, long h, unsigned char *data)
  894. {   SIZEL s;
  895.     s.cx=w; s.cy=h;
  896.     GpiImage(Handle,0,&s,((w-1)/8+1)*h,data);
  897. }
  898.  
  899. void PS::rectcopy (PS &ps, long x, long y, long w, long h,
  900.         long x1, long y1, int mode)
  901. {    POINTL a[4];
  902.     RECTL r;
  903.     r.xLeft=a[0].x=x; r.yBottom=a[0].y=y;
  904.     r.xRight=a[1].x=x+w-1; r.yTop=a[1].y=y+h-1;
  905.     a[2].x=x1; a[2].y=y1;
  906.     if (!GpiRectVisible(ps.handle(),&r)) return;
  907.     GpiBitBlt(ps.handle(),Handle,3,a,mode,BBO_IGNORE);
  908. }
  909.  
  910. void PS::setcharbox (long x, long y)
  911. {    SIZEF s;
  912.     s.cx=x*65536l; s.cy=y*65536l;
  913.     GpiSetCharBox(Handle,&s);
  914. }
  915.  
  916. //************ Bitmaps Presentation Spaces *****************
  917.  
  918. BitmapPS::BitmapPS (Window &window)
  919. {    PSZ pszData[4]={"Display",NULL,NULL,NULL};
  920.     BITMAPINFOHEADER2 bmp;
  921.     LONG alData[2],size;
  922.     DeviceHandle=DevOpenDC(program.hab(),OD_MEMORY,"*",4,
  923.         (PDEVOPENDATA)pszData,NULLHANDLE);
  924.     S.cx=window.width(); S.cy=window.height();
  925.     Handle=GpiCreatePS(program.hab(),DeviceHandle,&S,
  926.         PU_PELS|GPIA_ASSOC|GPIT_MICRO);
  927.     GpiQueryDeviceBitmapFormats(Handle,2,(PLONG)alData);
  928.     bmp.cbFix=(unsigned long)sizeof(BITMAPINFOHEADER2);
  929.     bmp.cx=S.cx; bmp.cy=S.cy;
  930.     Planes=bmp.cPlanes=alData[0];
  931.     Colorbits=bmp.cBitCount=alData[1];
  932.     bmp.ulCompression=BCA_UNCOMP;
  933.     bmp.cbImage=(((S.cx*(1<<bmp.cPlanes)*(1<<bmp.cBitCount))+31)
  934.         /32)*S.cy;
  935.     bmp.cxResolution=70; bmp.cyResolution=70;
  936.     bmp.cclrUsed=2; bmp.cclrImportant=0;
  937.     bmp.usUnits=BRU_METRIC; bmp.usReserved=0;
  938.     bmp.usRecording=BRA_BOTTOMUP; bmp.usRendering=BRH_NOTHALFTONED;
  939.     bmp.cSize1=0; bmp.cSize2=0;
  940.     bmp.ulColorEncoding=BCE_RGB; bmp.ulIdentifier=0;
  941.     size=sizeof(BITMAPINFO2)+
  942.         (sizeof(RGB2)*(1<<bmp.cPlanes)*(1<<bmp.cBitCount));
  943.     if (DosAllocMem((PVOID *)&Info,size,PAG_COMMIT|PAG_READ|PAG_WRITE))
  944.     {    Valid=0;
  945.         GpiDestroyPS(Handle);
  946.         DevCloseDC(DeviceHandle);
  947.     }
  948.     else Valid=1;
  949.     Info->cbFix=bmp.cbFix;
  950.     Info->cx=bmp.cx; Info->cy=bmp.cy;
  951.     Info->cPlanes=bmp.cPlanes; Info->cBitCount=bmp.cBitCount;
  952.     Info->ulCompression=BCA_UNCOMP;
  953.     Info->cbImage=((S.cx+31)/32)*S.cy;
  954.     Info->cxResolution=70; Info->cyResolution=70;
  955.     Info->cclrUsed=2; Info->cclrImportant=0;
  956.     Info->usUnits=BRU_METRIC;
  957.     Info->usReserved=0;
  958.     Info->usRecording=BRA_BOTTOMUP;
  959.     Info->usRendering=BRH_NOTHALFTONED;
  960.     Info->cSize1=0; Info->cSize2=0;
  961.     Info->ulColorEncoding=BCE_RGB; Info->ulIdentifier=0;
  962.     BitmapHandle=GpiCreateBitmap(Handle,&bmp,FALSE,NULL,Info);
  963.     GpiSetBitmap(Handle,BitmapHandle);
  964.     GpiErase(Handle);
  965. }
  966.  
  967. BitmapPS::BitmapPS (long w, long h)
  968. {    PSZ pszData[4]={"Display",NULL,NULL,NULL};
  969.     BITMAPINFOHEADER2 bmp;
  970.     LONG alData[2],size;
  971.     DeviceHandle=DevOpenDC(program.hab(),OD_MEMORY,"*",4,
  972.         (PDEVOPENDATA)pszData,NULLHANDLE);
  973.     S.cx=w; S.cy=h;
  974.     Handle=GpiCreatePS(program.hab(),DeviceHandle,&S,
  975.         PU_PELS|GPIA_ASSOC|GPIT_MICRO);
  976.     GpiQueryDeviceBitmapFormats(Handle,2,(PLONG)alData);
  977.     bmp.cbFix=(unsigned long)sizeof(BITMAPINFOHEADER2);
  978.     bmp.cx=S.cx; bmp.cy=S.cy;
  979.     Planes=bmp.cPlanes=alData[0];
  980.     Colorbits=bmp.cBitCount=alData[1];
  981.     bmp.ulCompression=BCA_UNCOMP;
  982.     bmp.cbImage=(((S.cx*(1<<bmp.cPlanes)*(1<<bmp.cBitCount))+31)
  983.         /32)*S.cy;
  984.     bmp.cxResolution=70; bmp.cyResolution=70;
  985.     bmp.cclrUsed=2; bmp.cclrImportant=0;
  986.     bmp.usUnits=BRU_METRIC; bmp.usReserved=0;
  987.     bmp.usRecording=BRA_BOTTOMUP; bmp.usRendering=BRH_NOTHALFTONED;
  988.     bmp.cSize1=0; bmp.cSize2=0;
  989.     bmp.ulColorEncoding=BCE_RGB; bmp.ulIdentifier=0;
  990.     size=sizeof(BITMAPINFO2)+
  991.         (sizeof(RGB2)*(1<<bmp.cPlanes)*(1<<bmp.cBitCount));
  992.     if (DosAllocMem((PVOID *)&Info,size,PAG_COMMIT|PAG_READ|PAG_WRITE))
  993.     {    Valid=0;
  994.         GpiDestroyPS(Handle);
  995.         DevCloseDC(DeviceHandle);
  996.     }
  997.     else Valid=1;
  998.     Info->cbFix=bmp.cbFix;
  999.     Info->cx=bmp.cx; Info->cy=bmp.cy;
  1000.     Info->cPlanes=bmp.cPlanes; Info->cBitCount=bmp.cBitCount;
  1001.     Info->ulCompression=BCA_UNCOMP;
  1002.     Info->cbImage=((S.cx+31)/32)*S.cy;
  1003.     Info->cxResolution=70; Info->cyResolution=70;
  1004.     Info->cclrUsed=2; Info->cclrImportant=0;
  1005.     Info->usUnits=BRU_METRIC;
  1006.     Info->usReserved=0;
  1007.     Info->usRecording=BRA_BOTTOMUP;
  1008.     Info->usRendering=BRH_NOTHALFTONED;
  1009.     Info->cSize1=0; Info->cSize2=0;
  1010.     Info->ulColorEncoding=BCE_RGB; Info->ulIdentifier=0;
  1011.     BitmapHandle=GpiCreateBitmap(Handle,&bmp,FALSE,NULL,Info);
  1012.     GpiSetBitmap(Handle,BitmapHandle);
  1013.     GpiErase(Handle);
  1014. }
  1015.  
  1016. BitmapPS::~BitmapPS ()
  1017. {   if (!Valid) return;
  1018.     GpiDeleteBitmap(BitmapHandle);
  1019.     DosFreeMem(Info);
  1020.     GpiDestroyPS(Handle);
  1021.     DevCloseDC(DeviceHandle);
  1022. }
  1023.  
  1024. void BitmapPS::copy (PS &ps, long x, long y, int mode)
  1025. {    POINTL a[4];
  1026.     RECTL r;
  1027.     r.xLeft=a[0].x=x; r.yBottom=a[0].y=y;
  1028.     r.xRight=a[1].x=x+S.cx; r.yTop=a[1].y=y+S.cy;
  1029.     a[2].x=0; a[2].y=0;
  1030.     if (!GpiRectVisible(ps.handle(),&r)) return;
  1031.     GpiBitBlt(ps.handle(),Handle,3,a,mode,BBO_IGNORE);
  1032. }
  1033.  
  1034. void BitmapPS::save (char *filename)
  1035. {    FILE *f;
  1036.     BITMAPFILEHEADER2 bfh;
  1037.     char *buffer;
  1038.     PBITMAPINFO2 pbmi;
  1039.     long size,colorsize,hdsize=20;
  1040.     unsigned long compression=BCA_UNCOMP;
  1041.     int bits;
  1042.     f=fopen(filename,"wb");
  1043.     if (!f)
  1044.     {   Warning("Could not open\nthat file.","Save Error");
  1045.         return;
  1046.     }
  1047.     bfh.usType=BFT_BMAP;
  1048.     if (Colorbits>8) bits=24;
  1049.     else bits=Colorbits;
  1050.     colorsize=((bits<=8)?(1<<bits):256)*sizeof(RGB2);
  1051.     size=((width()*bits+31)/32)*4*height();
  1052.     bfh.offBits=14+hdsize+colorsize;
  1053.     bfh.cbSize=14+hdsize+colorsize+size;
  1054.     buffer=(char *)malloc(size);
  1055.     pbmi=(PBITMAPINFO2)malloc(16+colorsize);
  1056.     memset(pbmi,0,sizeof(BITMAPINFOHEADER2));
  1057.     pbmi->cbFix=hdsize;
  1058.     pbmi->cPlanes=1;
  1059.     pbmi->cBitCount=bits;
  1060.     pbmi->ulCompression=compression;
  1061.     if (GpiQueryBitmapBits(handle(),0,height(),buffer,pbmi)!=height())
  1062.     {   Warning("Bitmap Save Error!","Error");
  1063.         goto end;
  1064.     }
  1065.     fwrite((char *)&bfh,14,1,f);
  1066.     fwrite((char *)pbmi,hdsize+colorsize,1,f);
  1067.     fwrite(buffer,1,size,f);
  1068.     end: free(pbmi);
  1069.     free(buffer);
  1070.     fclose(f);
  1071. }
  1072.  
  1073. // ************ Printer ***********************
  1074.  
  1075. Queues::Queues (char *name) : Queues(0),NQueues(0)
  1076. {   int Default=0,i;
  1077.     all();
  1078.     if (NQueues==0) return;
  1079.     if (name[0])
  1080.     {    for (i=0; i<NQueues; i++)
  1081.             if (!strcmp(name,Queues[i].pszName))
  1082.             {    Default=i;
  1083.                 break;
  1084.             }
  1085.     }
  1086.     memmove(&ChosenQueue,Queues+Default,sizeof(PRQINFO3));
  1087.     delete Queues;
  1088.     Queues=0;
  1089. }
  1090.  
  1091. PRQINFO3 *Queues::all ()
  1092. {   unsigned long ret,size;
  1093.     if (Queues) delete Queues;
  1094.     SplEnumQueue(NULL,3,Queues,0,
  1095.         &ret,&NQueues,&size,NULL);
  1096.     if (NQueues==0) return 0;
  1097.     Queues=(PRQINFO3 *)(new char[size]);
  1098.     SplEnumQueue(NULL,3,Queues,size,
  1099.         &ret,&NQueues,&size,NULL);
  1100.     return Queues;
  1101. }
  1102.  
  1103. PrinterPS::PrinterPS (Queues &q, char *name, int op)
  1104.     : Valid(0),Myname(name),Open(0)
  1105. {   if (q.number()==0)
  1106.     {    Valid.clear(); return;
  1107.     }
  1108.     memmove(&Queue,q.chosen(),sizeof(PRQINFO3));
  1109.     Valid.set();
  1110.     if (op) open();
  1111. }
  1112.  
  1113. PrinterPS::PrinterPS (char *name, int op)
  1114.     : Valid(0),Myname(name),Open(0)
  1115. {    Queues queues;
  1116.     if (queues.number()<1) return;
  1117.     Valid.set();
  1118.     memmove(&Queue,queues.chosen(),sizeof(PRQINFO3));
  1119.     if (op) open();
  1120. }
  1121.  
  1122. void PrinterPS::open ()
  1123. {   if (Open) return;
  1124.     Dos.pszLogAddress=Queue.pszName;
  1125.     Dos.pszDriverName=Queue.pszDriverName;
  1126.     *strchr(Dos.pszDriverName,'.')=0;
  1127.     Dos.pdriv=Queue.pDriverData;
  1128.     Dos.pszDataType="PM_Q_STD";
  1129.     Dos.pszComment=Myname;
  1130.     Dos.pszQueueProcName=Queue.pszPrProc;
  1131.     Dos.pszQueueProcParams=NULL;
  1132.     Dos.pszSpoolerParams=NULL;
  1133.     Dos.pszNetworkParams=NULL;
  1134.     HandlePrinter=DevOpenDC(program.hab(),OD_QUEUED,"*",9,
  1135.         (PDEVOPENDATA)&Dos,(HDC)0);
  1136.     if (HandlePrinter==DEV_ERROR)
  1137.     {   Valid.clear(); return;
  1138.     }
  1139.     Handle=GpiCreatePS(program.hab(),HandlePrinter,&S,
  1140.         PU_PELS|GPIA_ASSOC);
  1141.     if (DevEscape(HandlePrinter,DEVESC_STARTDOC,
  1142.         strlen(Myname),(char *)Myname,0,0)!=DEV_OK)
  1143.     {    Valid.clear(); return;
  1144.     }
  1145.     LONG alArray [CAPS_WIDTH_IN_CHARS];
  1146.     DevQueryCaps(HandlePrinter,CAPS_FAMILY,CAPS_WIDTH_IN_CHARS,
  1147.         (PLONG)alArray);
  1148.     S.cx=alArray[CAPS_WIDTH];
  1149.     S.cy=alArray[CAPS_HEIGHT];
  1150.     Open.set();
  1151. }
  1152.  
  1153. void PrinterPS::close ()
  1154. {   if (!Open) return;
  1155.     DevEscape(HandlePrinter,DEVESC_ENDDOC,0,0,0,0);
  1156.     DevCloseDC(HandlePrinter);
  1157.     GpiDestroyPS(Handle);
  1158.     Open.clear();
  1159. }
  1160.  
  1161. void PrinterPS::newpage ()
  1162. {    DevEscape(HandlePrinter,DEVESC_NEWFRAME,0,0,0,0);
  1163. }
  1164.  
  1165. // ************* Metafiles **********************
  1166.  
  1167. MetafilePS::MetafilePS (Window &window)
  1168. {   DEVOPENSTRUC dos;
  1169.     DEVOPENSTRUC dop;
  1170.     char *p;
  1171.     dop.pszLogAddress=(PSZ)NULL;
  1172.     dop.pszDriverName="DISPLAY";
  1173.     Hdc=DevOpenDC(program.hab(),
  1174.         OD_METAFILE,"*",2L,(PDEVOPENDATA)&dop,0);
  1175.     S.cx=window.width(); S.cy=window.height();
  1176.     Handle=GpiCreatePS(program.hab(),Hdc,&S,PU_PELS|GPIA_ASSOC);
  1177. }
  1178.  
  1179. MetafilePS::MetafilePS (Window &window, long w, long h)
  1180. {   DEVOPENSTRUC dos;
  1181.     DEVOPENSTRUC dop;
  1182.     char *p;
  1183.     dop.pszLogAddress=(PSZ)NULL;
  1184.     dop.pszDriverName="DISPLAY";
  1185.     Hdc=DevOpenDC(program.hab(),
  1186.         OD_METAFILE,"*",2L,(PDEVOPENDATA)&dop,0);
  1187.     S.cx=w; S.cy=h;
  1188.     Handle=GpiCreatePS(program.hab(),Hdc,&S,PU_PELS|GPIA_ASSOC);
  1189. }
  1190.  
  1191. MetafilePS::~MetafilePS ()
  1192. {    close();
  1193. }
  1194.  
  1195. void MetafilePS::close ()
  1196. {   if (Handle==NULLHANDLE) return;
  1197.     GpiAssociate(Handle,NULLHANDLE);
  1198.     GpiDestroyPS(Handle);
  1199.     Metafilehandle=DevCloseDC(Hdc);
  1200.     Handle=NULLHANDLE;
  1201. }
  1202.  
  1203. //***************** Bitmap Resources ***********************
  1204.  
  1205. Bitmap::Bitmap (int id, int width, int height)
  1206. {    PSZ pszData[4]={"Display",NULL,NULL,NULL};
  1207.     DeviceHandle=DevOpenDC(program.hab(),OD_MEMORY,"*",4,
  1208.         (PDEVOPENDATA)pszData,NULLHANDLE);
  1209.     S.cx=width; S.cy=height;
  1210.     PsHandle=GpiCreatePS(program.hab(),DeviceHandle,&S,
  1211.         PU_PELS|GPIA_ASSOC|GPIT_MICRO);
  1212.     Handle=GpiLoadBitmap(PsHandle,0,id,0,0);
  1213. }
  1214.  
  1215. Bitmap::~Bitmap ()
  1216. {   GpiDestroyPS(PsHandle);
  1217.     DevCloseDC(DeviceHandle);
  1218.     GpiDeleteBitmap(Handle);
  1219. }
  1220.  
  1221. //******************* Help ******************************
  1222.  
  1223.  
  1224. Help::Help (StandardWindow &window,
  1225.     int id, char *filename, char *title)
  1226. {    HELPINIT hini;
  1227.     hini.cb=sizeof(HELPINIT);
  1228.     hini.ulReturnCode=0L;
  1229.     hini.pszTutorialName=(PSZ)NULL;
  1230.     hini.phtHelpTable=
  1231.         (PHELPTABLE)MAKELONG(id,0xFFFF);
  1232.     hini.hmodHelpTableModule=(HMODULE)0;
  1233.     hini.hmodAccelActionBarModule=(HMODULE)0;
  1234.     hini.idAccelTable=0;
  1235.     hini.idActionBar=0;
  1236.     hini.pszHelpWindowTitle=title;
  1237.     hini.fShowPanelId = CMIC_HIDE_PANEL_ID;
  1238.     hini.pszHelpLibraryName=filename;
  1239.     Handle=WinCreateHelpInstance(program.hab(),&hini);
  1240.     if (!Handle) { Valid=0; return; }
  1241.     Valid=1;
  1242.     WinAssociateHelpInstance(Handle,window.framehandle());
  1243. }
  1244.  
  1245. // ****************** Dialogs *************************
  1246.  
  1247. static Dialog *activedlg,*dlgs=0;
  1248.  
  1249. static MRESULT EXPENTRY dialogproc (HWND hwnd, unsigned long msg,
  1250.     MPARAM mp1, MPARAM mp2)
  1251. {   Dialogitem *item;
  1252.     Dialog *dlg,*dlg1;
  1253.     int result;
  1254.     if (!activedlg) // search dialog using window handle
  1255.     {    dlg=dlgs;
  1256.         while (dlg)
  1257.         {    if (dlg->Handle==hwnd) break;
  1258.             dlg=dlg->Next;
  1259.         }
  1260.         if (!dlg) // should not happen
  1261.             return WinDefDlgProc(hwnd,msg,mp1,mp2);
  1262.     }
  1263.     else dlg=activedlg;
  1264.     switch (msg)
  1265.     {   case WM_INITDLG : // initialize activedlg
  1266.             activedlg->Handle=hwnd;
  1267.             item=activedlg->Items;
  1268.             while (item)
  1269.             {    item->init();
  1270.                 item=item->next();
  1271.             }
  1272.             activedlg->start();
  1273.             // put dialog into dialog chain
  1274.             activedlg->Next=dlgs;
  1275.             dlgs=activedlg;
  1276.             activedlg=0; // activedlg unusable
  1277.             break;
  1278.         case WM_CHAR :
  1279.             if (dlg->key(SHORT1FROMMP(mp1),SHORT1FROMMP(mp2),
  1280.                 SHORT2FROMMP(mp2))) break;
  1281.             goto def;
  1282.         case WM_HELP :
  1283.             if (dlg->H) dlg->H->display(dlg->Hid);
  1284.             break;
  1285.         case WM_CONTROL :
  1286.             result=dlg->Result=(SHORT1FROMMP(mp1));
  1287.             item=dlg->Items;
  1288.             while (item)
  1289.             {    if (item->id()==result)
  1290.                 {    item->command(mp1,mp2);
  1291.                     return 0;
  1292.                 }
  1293.                 item=item->next();
  1294.             }
  1295.             break;
  1296.         case WM_CLOSE :
  1297.             if (dlg->close())
  1298.             {    result=-1;
  1299.                 goto finish;
  1300.             }
  1301.             return 0;
  1302.         case WM_COMMAND :
  1303.             result=dlg->Result=(SHORT1FROMMP(mp1));
  1304.             item=dlg->Items;
  1305.             while (item)
  1306.             {    if (item->id()==result)
  1307.                 {    item->command(mp1,mp2);
  1308.                     return 0;
  1309.                 }
  1310.                 item=item->next();
  1311.             }
  1312.             if (!dlg->handler(result))
  1313.             {   finish :
  1314.                 item=dlg->Items;
  1315.                 while (item)
  1316.                 {    item->exit();
  1317.                     item=item->next();
  1318.                 }
  1319.                 dlg->stop();
  1320.                 // remove dialog from dialog chain
  1321.                 if (dlgs==dlg) dlgs=dlg->Next;
  1322.                 else
  1323.                 {    dlg1=dlgs;
  1324.                     while (dlg1)
  1325.                     {    if (dlg1->Next==dlg) break;
  1326.                         dlg1=dlg1->Next;
  1327.                     }
  1328.                     if (dlg1) dlg1->Next=dlg->Next;
  1329.                 }
  1330.                 // close dialog
  1331.                 WinDismissDlg(hwnd,SHORT1FROMMP(mp1));
  1332.             }
  1333.             break;
  1334.         default :
  1335.             def: return WinDefDlgProc(hwnd,msg,mp1,mp2);
  1336.     }
  1337.     return 0;
  1338. }
  1339.  
  1340. void Dialog::init (Window &window, int id)
  1341. {    W=&window;
  1342.     Id=id;
  1343.     Items=0;
  1344. }
  1345.  
  1346. Dialog::Dialog (Window &window, int id, Help &h, int hid) :
  1347.     S("",256)
  1348. {    init(window,id);
  1349.     H=&h; Hid=hid; Next=0;
  1350. }
  1351.  
  1352. Dialog::Dialog (Window &window, int id) :
  1353.     S("",256)
  1354. {    init(window,id);
  1355.     H=0; Next=0;
  1356. }
  1357.  
  1358. Dialogitem *Dialog::entry (Dialogitem *item)
  1359. {    Dialogitem *note=Items;
  1360.     Items=item;
  1361.     return note;
  1362. }
  1363.  
  1364. void Dialog::carryout ()
  1365. {   activedlg=this;
  1366.     Handle=WinDlgBox(HWND_DESKTOP,W->handle(),dialogproc,
  1367.         (HMODULE)0,Id,NULL);
  1368. }
  1369.  
  1370. void DialogPanel::carryout ()
  1371. {   activedlg=this;
  1372.     Handle=WinLoadDlg(HWND_DESKTOP,W->handle(),dialogproc,
  1373.         (HMODULE)0,Id,NULL);
  1374. }
  1375.  
  1376. char *Dialog::gettext (int id, char *text, long size)
  1377. {   HWND handle=WinWindowFromID(Handle,id);
  1378.     WinQueryWindowText(handle,size,text);
  1379.     return text;
  1380. }
  1381.  
  1382. char *Dialog::gettext (int id)
  1383. {   HWND handle=WinWindowFromID(Handle,id);
  1384.     WinQueryWindowText(handle,S.size(),(PSZ)S.text());
  1385.     return S;
  1386. }
  1387.  
  1388. void Dialog::settext (int id, char *text)
  1389. {    HWND handle=WinWindowFromID(Handle,id);
  1390.     WinSetWindowText(handle,text);
  1391. }
  1392.  
  1393. MRESULT Dialog::message (int id, int msg,
  1394.     Parameter mp1, Parameter mp2)
  1395. {    HWND h;
  1396.     h=WinWindowFromID(Handle,id);
  1397.     return WinSendMsg(h,msg,mp1,mp2);
  1398. }
  1399.  
  1400. void Dialog::move (LONG x, LONG y)
  1401. {    WinSetWindowPos(Handle,NULLHANDLE,x,y,0,0,SWP_MOVE);
  1402. }
  1403.  
  1404. void Dialog::getframe (LONG &x, LONG &y, LONG &w, LONG &h)
  1405. {    SWP s;
  1406.     WinQueryWindowPos(Handle,&s);
  1407.     x=s.x; y=s.y; w=s.cx; h=s.cy;
  1408. }
  1409.  
  1410. //*********** Window Dialogs ********************
  1411.  
  1412. WindowDialog::WindowDialog (StandardWindow &w) : Dialog(w,0)
  1413. {   Handle=w.handle();
  1414.     w.setdialog(*this);
  1415. }
  1416.  
  1417. int WindowDialog::command (Parameter p1, Parameter p2)
  1418. {   Result=p1.lower();
  1419.     Dialogitem *item=Items;
  1420.     while (item)
  1421.     {    if (item->id()==Result)
  1422.         {    item->command(p1,p2);
  1423.             return 1;
  1424.         }
  1425.         item=item->next();
  1426.     }
  1427.     return 0;
  1428. }
  1429.  
  1430. //*************** Dialog Items ******************
  1431.  
  1432. Dialogitem::Dialogitem (int id, Dialog &dialog)
  1433. {    Id=id;
  1434.     D=&dialog;
  1435.     Next=dialog.entry(this);
  1436. }
  1437.  
  1438. void Dialogitem::size (long w, long h)
  1439. {   WinSetWindowPos(handle(),NULLHANDLE,0,0,
  1440.         w,h,SWP_SIZE);
  1441. }
  1442.  
  1443. void Dialogitem::pos (long x, long y)
  1444. {   WinSetWindowPos(handle(),NULLHANDLE,x,y,
  1445.         0,0,SWP_MOVE);
  1446. }
  1447.  
  1448. void Dialogitem::sizepos (long x, long y, long w, long h)
  1449. {   WinSetWindowPos(handle(),NULLHANDLE,x,y,
  1450.         w,h,SWP_SIZE|SWP_MOVE);
  1451. }
  1452.  
  1453. ButtonItem::ButtonItem (WindowDialog &d,
  1454.     long x, long y, long w, long h, char *text,
  1455.     int style) :
  1456.         Dialogitem(d.newid(),d),Pressed(0)
  1457. {    WinCreateWindow(d.handle(),WC_BUTTON,
  1458.         text,WS_VISIBLE|BS_PUSHBUTTON|style,
  1459.         x,y,w,h,
  1460.         d.handle(),HWND_TOP,id(),
  1461.         0,0);
  1462. }
  1463.  
  1464. ButtonItem::ButtonItem (WindowDialog &d,
  1465.     long x, long y, long w, long h, int iconid,
  1466.     int style) :
  1467.         Dialogitem(d.newid(),d),Pressed(0)
  1468. {   char s[16];
  1469.     sprintf(s,"#%d",iconid);
  1470.     WinCreateWindow(d.handle(),WC_BUTTON,
  1471.         s,WS_VISIBLE|BS_PUSHBUTTON|style,
  1472.         x,y,w,h,
  1473.         d.handle(),HWND_TOP,id(),
  1474.         0,0);
  1475. }
  1476.  
  1477. StringItem::StringItem (WindowDialog &d,
  1478.         long x, long y, long w, long h,
  1479.         char *string, int length, int style)
  1480.         : Dialogitem(d.newid(),d),Length(length),S(string),
  1481.             Changed(0)
  1482. {    WinCreateWindow(d.handle(),WC_ENTRYFIELD,
  1483.         string,WS_VISIBLE|style,
  1484.         x,y,w,h,
  1485.         d.handle(),HWND_TOP,id(),
  1486.         0,0);
  1487. }
  1488.  
  1489. void StringItem::init ()
  1490. {   int size=strlen(S)+1;
  1491.     if (Length>size) size=Length;
  1492.     limit(size);
  1493.     D->settext(Id,S);
  1494.     D->message(Id,EM_SETREADONLY,Readonly);
  1495.     D->message(Id,EM_QUERYCHANGED);
  1496.     Changed.clear();
  1497. }
  1498.  
  1499. int StringItem::changed ()
  1500. {   if (Changed) return 1;
  1501.     if (D->message(Id,EM_QUERYCHANGED))
  1502.     {    S.copy(D->gettext(Id));
  1503.         Changed.set();
  1504.         return 1;
  1505.     }
  1506.     return 0;
  1507. }
  1508.  
  1509. void StringItem::exit ()
  1510. {   if (D->message(Id,EM_QUERYCHANGED))
  1511.     {    S.copy(D->gettext(Id));
  1512.     }
  1513.     Changed.clear();
  1514. }
  1515.  
  1516. void StringItem::limit (int length)
  1517. {    D->message(Id,EM_SETTEXTLIMIT,Parameter(length));
  1518. }
  1519.  
  1520. void CheckItem::init ()
  1521. {   D->message(Id,BM_SETCHECK,(int)F);
  1522. }
  1523.  
  1524. void CheckItem::exit ()
  1525. {    F=(long)D->message(Id,BM_QUERYCHECK,1);
  1526. }
  1527.  
  1528. void CheckItem::command (Parameter mp1, Parameter mp2)
  1529. {   if (mp1.higher()==BN_CLICKED || mp1.higher()==BN_DBLCLICKED)
  1530.     {    F=(long)D->message(Id,BM_QUERYCHECK);
  1531.         notify();
  1532.     }
  1533. }
  1534.  
  1535. void RadioButton::init ()
  1536. {   if (F) D->message(Id,BM_CLICK,1);
  1537. }
  1538.  
  1539. void RadioButton::command (Parameter mp1, Parameter mp2)
  1540. {    R->notify();
  1541.     R->sel(N);
  1542. }
  1543.  
  1544. RadioItem::RadioItem (int *ids, int n, Dialog &dialog, int sel)
  1545.     : N(n),Ids(ids),I(sel),D(&dialog)
  1546. {    int i;
  1547.     Rb=new RadioButton *[N];
  1548.     for (i=0; i<N; i++)
  1549.         Rb[i]=new RadioButton(Ids[i],dialog,i+1==I,*this,i+1);
  1550. }
  1551.  
  1552. RadioItem::~RadioItem ()
  1553. {    int i;
  1554.     for (i=0; i<N; i++) delete Rb[i];
  1555.     delete Rb;
  1556. }
  1557.  
  1558. void RadioItem::sel (int s)
  1559. {    I=s;
  1560. }
  1561.  
  1562. void DoubleItem::init ()
  1563. {    sprintf(S,"%-0.10g",X);
  1564.     D->settext(Id,S);
  1565.     D->message(Id,EM_SETREADONLY,Readonly);
  1566. }
  1567.  
  1568. void DoubleItem::exit ()
  1569. {     S.copy(D->gettext(Id),64);
  1570.     sscanf(S,"%lg",&X);
  1571. }
  1572.  
  1573. void LongItem::init ()
  1574. {    sprintf(S,"%-ld",N);
  1575.     D->settext(Id,S);
  1576.     D->message(Id,EM_SETREADONLY,Readonly);
  1577. }
  1578.  
  1579. void LongItem::exit ()
  1580. {     S.copy(D->gettext(Id),64);
  1581.     sscanf(S,"%ld",&N);
  1582. }
  1583.  
  1584. void SpinItem::init ()
  1585. {    D->message(Id,SPBM_SETLIMITS,Upper,Lower);
  1586.     D->message(Id,SPBM_SETCURRENTVALUE,N);
  1587. }
  1588.  
  1589. void SpinItem::exit ()
  1590. {    D->message(Id,SPBM_QUERYVALUE,&N,Parameter(0,SPBQ_ALWAYSUPDATE));
  1591. }
  1592.  
  1593. void SliderItem::init ()
  1594. {    D->message(Id,SLM_SETSLIDERINFO,
  1595.         Parameter(SMA_SLIDERARMPOSITION,SMA_INCREMENTVALUE),
  1596.         Parameter(N));
  1597. }
  1598.  
  1599. void SliderItem::exit ()
  1600. {    N=(long)D->message(Id,SLM_QUERYSLIDERINFO,
  1601.         Parameter(SMA_SLIDERARMPOSITION,SMA_INCREMENTVALUE));
  1602. }
  1603.  
  1604. void SliderItem::tick (int n, int size)
  1605. {    D->message(Id,SLM_SETTICKSIZE,Parameter(n,size));
  1606. }
  1607.  
  1608. void SliderItem::label (int n, char *text)
  1609. {    D->message(Id,SLM_SETSCALETEXT,Parameter(n),Parameter(text));
  1610. }
  1611.  
  1612. void SliderItem::command (Parameter mp1, Parameter mp2)
  1613. {   switch (mp1.higher())
  1614.     {    case SLN_CHANGE : N=mp2; notify(); break;
  1615.         case SLN_SLIDERTRACK : N=mp2; changing(N); break;
  1616.     }
  1617. }
  1618.  
  1619. void ValuesetItem::select (int row, int col)
  1620. {    D->message(Id,VM_SELECTITEM,Parameter(row,col));
  1621. }
  1622.  
  1623. void ValuesetItem::setbitmap (int row, int col, Bitmap &b)
  1624. {    D->message(Id,VM_SETITEMATTR,Parameter(row,col),
  1625.         Parameter(VIA_BITMAP,1));
  1626.     D->message(Id,VM_SETITEM,Parameter(row,col),
  1627.         Parameter((long)b.handle()));
  1628. }
  1629.  
  1630. void ValuesetItem::setcolor (int row, int col, unsigned long color)
  1631. {    D->message(Id,VM_SETITEMATTR,Parameter(row,col),
  1632.         Parameter(VIA_RGB,1));
  1633.     WindowPS ps(*D->w());
  1634.     color=GpiQueryRGBColor(ps.handle(),0,color);
  1635.     D->message(Id,VM_SETITEM,Parameter(row,col),
  1636.         Parameter((long)color));
  1637. }
  1638.  
  1639. void ValuesetItem::exit ()
  1640. {    Parameter p(D->message(Id,VM_QUERYSELECTEDITEM,0));
  1641.     Col=p.higher(); Row=p.lower();
  1642. }
  1643.  
  1644. void ValuesetItem::command (Parameter mp1, Parameter mp2)
  1645. {    if (mp1.higher()==VN_SELECT)
  1646.     {    Row=mp2.lower(); Col=mp2.higher();
  1647.         notify();
  1648.     }
  1649. }
  1650.  
  1651. void ListItem::insert (char *text)
  1652. {    D->message(Id,LM_INSERTITEM,Parameter(LIT_END),Parameter(text));
  1653. }
  1654.  
  1655. void ListItem::select (int sel)
  1656. {    D->message(Id,LM_SELECTITEM,Parameter(sel),Parameter(1));
  1657.     Selection=sel;
  1658. }
  1659.  
  1660. void ListItem::exit ()
  1661. {    Selection=Parameter(D->message(Id,LM_QUERYSELECTION)).lower();
  1662. }
  1663.  
  1664. void ListItem::command (Parameter mp1, Parameter mp2)
  1665. {    if (mp1.higher()==LN_ENTER)
  1666.     {   Selection=Parameter(D->message(Id,LM_QUERYSELECTION)).lower();
  1667.         notify();
  1668.     }
  1669. }
  1670.  
  1671. MultilineItem::MultilineItem (WindowDialog &d,
  1672.     long x, long y, long w, long h,
  1673.     char *text, long length, int style)
  1674.         : Dialogitem(d.newid(),d),S(text,length),
  1675.             Changed(0)
  1676. {    WinCreateWindow(d.handle(),WC_MLE,
  1677.         text,WS_VISIBLE|style,
  1678.         x,y,w,h,
  1679.         d.handle(),HWND_TOP,id(),0,0);
  1680. }
  1681.  
  1682. void MultilineItem::init ()
  1683. {    limit(S.size());
  1684.     D->settext(Id,S);
  1685.     D->message(Id,MLM_SETSEL,0,0);
  1686.     D->message(Id,MLM_SETREADONLY,Readonly);
  1687.     D->message(Id,MLM_SETCHANGED,0);
  1688.     Changed.clear();
  1689. }
  1690.  
  1691. void MultilineItem::limit (int length)
  1692. {    D->message(Id,MLM_SETTEXTLIMIT,Parameter(length));
  1693. }
  1694.  
  1695. int MultilineItem::changed ()
  1696. {   if (Changed) return 1;
  1697.     if (D->message(Id,MLM_QUERYCHANGED))
  1698.     {   D->message(Id,MLM_SETCHANGED,0);
  1699.         S.copy(D->gettext(Id,S,S.size()));
  1700.         Changed.set();
  1701.         return 1;
  1702.     }
  1703.     return 0;
  1704. }
  1705.  
  1706. void MultilineItem::exit ()
  1707. {   if (D->message(Id,MLM_QUERYCHANGED))
  1708.     {    D->message(Id,MLM_SETCHANGED,0);
  1709.         S.copy(D->gettext(Id,S,S.size()));
  1710.     }
  1711.     Changed.clear();
  1712. }
  1713.  
  1714. //******************* File Selector ********************
  1715.  
  1716. FileSelector::FileSelector (Window &window,
  1717.         char *filter, int saving,
  1718.         char *title, char *ok) : Filter(filter),Title(title)
  1719.  
  1720. {    memset(&Fd,0,sizeof(FILEDLG));
  1721.  
  1722.     Fd.cbSize=sizeof(FILEDLG);
  1723.     Fd.fl=FDS_CENTER|FDS_ENABLEFILELB
  1724.         |(saving?FDS_SAVEAS_DIALOG:FDS_OPEN_DIALOG);
  1725.     Fd.pszTitle=(char *)Title;
  1726.     if (!ok)
  1727.     {    if (saving) Ok.copy("Save");
  1728.  
  1729.         else Ok.copy("Load");
  1730.  
  1731.     }
  1732.  
  1733.     else Ok.copy(ok);
  1734.  
  1735.     Fd.pszOKButton=(char *)Ok;
  1736.  
  1737.     strcpy(Fd.szFullFile,"");
  1738.  
  1739.     W=&window;
  1740.  
  1741. }
  1742.  
  1743.  
  1744. char *FileSelector::select ()
  1745.  
  1746. {   char *p=Filter.filename();
  1747.  
  1748.     String s(Fd.szFullFile,CCHMAXPATH);
  1749.  
  1750.     s.stripfilename();
  1751.  
  1752.     strncpy(Fd.szFullFile,s,CCHMAXPATH-16);
  1753.  
  1754.     Fd.szFullFile[CCHMAXPATH-16]=0;
  1755.  
  1756.     strcat(Fd.szFullFile,p);
  1757.  
  1758.     Freturn=WinFileDlg(HWND_DESKTOP,W->handle(),&Fd);
  1759.  
  1760.     if (!Freturn || Fd.lReturn!=DID_OK) return 0;
  1761.     return Fd.szFullFile;
  1762.  
  1763. }
  1764.  
  1765. char *FileSelector::select (char *name)
  1766.  
  1767. {   strncpy(Fd.szFullFile,name,CCHMAXPATH-1);
  1768.  
  1769.     Fd.szFullFile[CCHMAXPATH-1]=0;
  1770.  
  1771.     Freturn=WinFileDlg(HWND_DESKTOP,W->handle(),&Fd);
  1772.  
  1773.     if (!Freturn || Fd.lReturn!=DID_OK) return 0;
  1774.     return Fd.szFullFile;
  1775.  
  1776. }
  1777.  
  1778. // ************ Font Selector *********
  1779.  
  1780. int FontSelector::select (Window &window)
  1781. {   WindowPS *sps=0;
  1782.     PrinterPS *pps=0;
  1783.     if (Type&screen) sps=new WindowPS(window);
  1784.     if (Type&printer) pps=new PrinterPS();
  1785.     memset(&Fd,0,sizeof(FONTDLG));
  1786.     Fd.cbSize=sizeof(FONTDLG);
  1787.     if (sps) Fd.hpsScreen=sps->handle();
  1788.     if (pps) Fd.hpsPrinter=pps->handle();
  1789.     Fd.pszFamilyname=Facename;
  1790.     Fd.usFamilyBufLen=Facename.size();
  1791.     Fd.fxPointSize=long(Pointsize*65536);
  1792.     Fd.fl=FNTS_CENTER;
  1793.     Fd.clrFore=CLR_BLACK;
  1794.     Fd.clrBack=CLR_WHITE;
  1795.     Fd.fAttrs.usCodePage=Codepage;
  1796.     Result=0;
  1797.     WinFontDlg(HWND_DESKTOP,window.handle(),&Fd);
  1798.     Result=(Fd.lReturn==DID_OK);
  1799.     if (sps) delete sps;
  1800.     if (pps) delete pps;
  1801.     return Result;
  1802. }
  1803.  
  1804. // *************** handling fonts **************************
  1805.  
  1806. Fonts::Fonts (PS &ps)
  1807. {    Count=0;
  1808.     Count=GpiQueryFonts(ps.handle(),
  1809.         QF_PUBLIC,0,&Count,sizeof(FONTMETRICS),0);
  1810.     AllFonts=new FONTMETRICS[Count];
  1811.     GpiQueryFonts(ps.handle(),
  1812.         QF_PUBLIC,0,&Count,sizeof(FONTMETRICS),AllFonts);
  1813. }
  1814.  
  1815. Fonts::~Fonts ()
  1816. {    delete AllFonts;
  1817. }
  1818.  
  1819. Font::Font (FontSelector &fs)
  1820. {    memcpy(&Fat,fs.fat(),sizeof(FATTRS));
  1821. }
  1822.  
  1823. Font::Font (char *name, long h, long w, long a, long t, int cp)
  1824. {    Fat.usRecordLength=sizeof(FATTRS);
  1825.     Fat.fsSelection=0;
  1826.     Fat.lMatch=0;
  1827.     strncpy(Fat.szFacename,name,FACESIZE);
  1828.     Fat.idRegistry=0;
  1829.     Fat.usCodePage=cp;
  1830.     Fat.lMaxBaselineExt=h;
  1831.     Fat.lAveCharWidth=w;
  1832.     Fat.fsType=t;
  1833.     Fat.fsFontUse=a;
  1834. }
  1835.  
  1836. Font::Font (long id, char *name, long fontparams)
  1837. {    Fat.usRecordLength=sizeof(FATTRS);
  1838.     Fat.fsSelection=fontparams;
  1839.     Fat.lMatch=id;
  1840.     strncpy(Fat.szFacename,name,FACESIZE);
  1841.     Fat.idRegistry=0;
  1842.     Fat.usCodePage=0;
  1843.     Fat.lMaxBaselineExt=0;
  1844.     Fat.lAveCharWidth=0;
  1845.     Fat.fsType=0;
  1846.     Fat.fsFontUse=0;
  1847. }
  1848.  
  1849. // ************ Profile ***************
  1850.  
  1851. void Profile::writestring (char *k, char *i)
  1852. {    PrfWriteProfileString(P,S,k,i);
  1853. }
  1854.  
  1855. void Profile::writedouble (char *k, double x)
  1856. {    PrfWriteProfileData(P,S,k,&x,sizeof(double));
  1857. }
  1858.  
  1859. void Profile::writelong (char *k, long x)
  1860. {    PrfWriteProfileData(P,S,k,&x,sizeof(long));
  1861. }
  1862.  
  1863. void Profile::writeint (char *k, int x)
  1864. {    PrfWriteProfileData(P,S,k,&x,sizeof(int));
  1865. }
  1866.  
  1867. char *Profile::readstring (char *k, char *d, long size)
  1868. {    H.copy(d,size);
  1869.     PrfQueryProfileString(P,S,k,(char *)H,(char *)H,size);
  1870.     return H;
  1871. }
  1872.  
  1873. double Profile::readdouble (char *k, double x)
  1874. {   double res;
  1875.     unsigned long size=sizeof(double);
  1876.     if (PrfQueryProfileData(P,S,k,&res,&size)) return res;
  1877.     else return x;
  1878. }
  1879.  
  1880. long Profile::readlong (char *k, long x)
  1881. {   long res;
  1882.     unsigned long size=sizeof(long);
  1883.     if (PrfQueryProfileData(P,S,k,&res,&size)) return res;
  1884.     else return x;
  1885. }
  1886.  
  1887. int Profile::readint (char *k, int x)
  1888. {   int res;
  1889.     unsigned long size=sizeof(int);
  1890.     if (PrfQueryProfileData(P,S,k,&res,&size)) return res;
  1891.     else return x;
  1892. }
  1893.  
  1894. // ********** Clipboard ***************
  1895.  
  1896. void Clipboard::copy (MetafilePS &meta)
  1897. {   meta.close();
  1898.     if (!WinOpenClipbrd(program.hab())) return;
  1899.     WinEmptyClipbrd(program.hab());
  1900.     WinSetClipbrdData(program.hab(),
  1901.         meta.metafilehandle(),CF_METAFILE,CFI_HANDLE);
  1902.     WinCloseClipbrd(program.hab());
  1903. }
  1904.  
  1905.